Глава 3

ЭЛЕМЕНТЫ ЯЗЫКА

3.1. АЛФАВИТ

Алфавит языка Турбо Паскаль включает буквы, цифры, шестнадцатеричные цифры, специальные символы, пробелы и зарезервированные слова.

Буквы - это буквы латинского алфавита от а до z и от А до Z, а также знак подчеркивания _ (код ASCII 95). В Турбо Паскале нет различия между прописными и строчными буквами алфавита, если только они не входят в символьные и строковые выражения.

Цифры - арабские цифры от 0 до 9.

Каждая шестнадцатеричная цифра имеет значение от 0 до 15. Первые 10 значений обозначаются арабскими цифрами 0...9, остальные шесть - латинскими буквами A...F или a...f.

Специальные символы Турбо Паскаля - это символы

+ - * / = ,' . : ; < > [ ] ( ) { } ^ @ $ #

К специальным символам относятся также следующие пары символов:

 <> <= >= := (* *) (. .)

В программе эти пары символов нельзя разделять пробелами, если они используются как знаки операций отношения или ограничители комментария. Символы (. и .) могут употребляться соответственно вместо [ и ].

Особое место в алфавите языка занимают пробелы, к которым относятся любые символы ASCII в диапазоне кодов от 0 до 32. Эти символы рассматриваются как ограничители идентификаторов, констант, чисел, зарезервированных слов. Несколько следующих друг за другом пробелов считаются одним пробелом (последнее не относится к строковым константам).

В Турбо Паскале имеются следующие зарезервированные слова:

and           end              nil         shr

asm           file             not         string

array         for              object      then

begin         function         of          to

case          goto             or          type

const         if               packed      unit

constructor   implementation   procedure   until

destructor    in               program     uses

div           inline           record      var

do            interface        repeat      while

downto        label            set         with

else          mod              shl         xor

Зарезервированные слова не могут использоваться в качестве идентификаторов. Стандартные директивы первоначально связаны с некоторыми стандартными объявлениями в программе. К ним относятся:

absolute    far        near

assembler   forward    private

external    interrupt  virtual

Как и зарезервированные слова, стандартные директивы в окне редактора Турбо Паскаля выделяются цветом, тем не менее Вы можете переопределить любую стандартную директиву, т.е. объявить одноименный идентификатор. Стандартные директивы PRIVATE и VIRTUAL действуют только в пределах объявления объектов.

3.2. ИДЕНТИФИКАТОРЫ

Идентификаторы в Турбо Паскале - это имена констант, переменных, меток, типов, объектов, процедур, функций, модулей, программ и полей в записях. Идентификаторы могут иметь произвольную длину, но значащими (уникальными в области определения) являются только первые 63 символа.

Идентификатор всегда начинается буквой, за которой могут следовать буквы и цифры. Напомню, что буквой считается также символ подчеркивания, поэтому идентификатор может начинаться этим символом и даже состоять только из одного или нескольких символов подчеркивания. Пробелы и специальные символы алфавита не могут входить в идентификатор.

Примеры правильных идентификаторов:

а

ALPHA

MyProgramIsBestProgram

date_27_sep_39

external

_beta

Примеры неправильных идентификаторов:

1Program {начинается цифрой}

block#l {содержит специальный символ}

My Prog {содержит пробел}

mod {зарезервированное слово}

3.3. КОНСТАНТЫ

В качестве констант в Турбо Паскале могут использоваться целые, вещественные и шестнадцатеричные числа, логические константы, символы, строки символов, конструкторы множеств и признак неопределенного указателя NIL.

Целые числа записываются со знаком или без него по обычным правилам и могут иметь значение от -2147483648 до +2147483647. Следует учесть, что, если целочисленная константа выходит за указанные границы, компилятор дает сообщение об ошибке. Такие константы должны записываться с десятичной точкой, т.е. определяться как вещественные числа.

Вещественные числа записываются со знаком или без него с использованием десятичной точки и/или экспоненциальной части. Экспоненциальная часть начинается символом е или Е, за которым могут следовать знаки «+» или «-» и десятичный порядок. Символ е (Е) означает десятичный порядок и имеет смысл «умножить на 1.0 в степени». Например,

3.14Е5 - 3.14 умножить на 10 в степени 5;

-17е-2 - минус 17 умножить на 10 в степени минус 2.

Если в записи вещественного числа присутствует десятичная точка, перед точкой и за ней должно быть хотя бы по одной цифре. Если используется символ экспоненциальной части е (Е), за ним должна следовать хотя бы одна цифра десятичного порядка.

Шестнадцатеричное число состоит из шестнадцатеричных цифр, которым предшествует знак доллара $ (код 36 в ASCII). Диапазон шестнадцатеричных чисел - от $00000000 ДО $FFFFFFFF.

Логическая константа - это либо слово FALSE (ложь), либо слово TRUE (истина).

Символьная константа - это любой символ ПК, заключенный в апострофы:

'z' - символ z;

'Ф' - символ Ф.

Если необходимо записать собственно символ апострофа, он удваивается: 

'''' - символ ' (апостроф).

Допускается использование записи символа путем указания его внутреннего кода, которому предшествует символ # (код 35), например:

#97 - символ а;

#90 - символ Z;

#39 - символ ';

#13 - символ CR.

Строковая константа - любая последовательность символов (кроме символа CR -возврат каретки), заключенная в апострофы. Если в строке нужно указать сам символ апострофа, он удваивается, например:

'Это - строка символов;

 'That' 's string.'.

Строка символов может быть пустой, т.е. не иметь никаких символов в обрамляющих ее апострофах. Строку можно составлять из кодов нужных символов с предшествующими каждому коду символами #, например, строка #83#121#109#98#11#108 эквивалентна строке ' Symbol'.

Наконец, в строке можно чередовать части, записанные в обрамляющих апострофах, с частями, записанными кодами. Таким способом можно вставлять в строки любые управляющие символы, в том числе и символ CR (код 13), например:

#7'Ошибка !'#13'Нажмите любую клавишу ...'#7 .

Конструктор множества - список элементов множества, обрамленный квадратными скобками, например:

[1,2,4..7,12] 

[blue, red] 

[] 

[true]

В отличие от стандартного Паскаля, в Турбо Паскале разрешается в объявлении констант использовать произвольные выражения, операндами которых могут быть ранее объявленные нетипизированные константы, имена типов и объектов, а также следующие функции от них;

abs     lo     ptr     swap

chr     odd    rpund   trunc

hi      ord    sizeof

length  pred   succ

Например:

const

MaxReal = Maxlnt div SizeOf(real); 

NumChars = ord('Z') - ord('a') + 1; 

Ln10 = 2.302585092994; 

Ln10R = 1 / Lnl0;.

3.4. ВЫРАЖЕНИЯ

Основными элементами, из которых конструируется исполняемая часть программы, являются константы, переменные и обращения к функциям. Каждый из этих элементов характеризуется своим значением и принадлежит к какому-либо типу данных. С помощью знаков операций и скобок из них можно составлять выражения, которые фактически представляют собой правила получения новых значений.

Частным случаем выражения может быть просто одиночный элемент, т.е. константа, переменная или обращение к функции. Значение такого выражения имеет, естественно, тот же тип, что и сам элемент. В более общем случае выражение состоит из нескольких элементов (операндов) и знаков операций, а тип его значения определяется типом операндов и видом примененных к ним операций. Примеры выражений:

Y

21

(а + b) * с

sin(t)

а > 2

not Flag and (а = b)

NIL

[1, 3..7] * set1

3.5. ОПЕРАЦИИ

В Турбо Паскале определены следующие операции:

унарные                      not, @;

мультипликативные  *, /, div, mod, and, shl, shr;

аддитивные                +, -, or, xor;

отношения                  =, <>, <, >, <=, >=,in.

Приоритет операций убывает в указанном порядке, т.е. наивысшим приоритетом обладают унарные операции, низшим - операции отношения. Порядок выполнения нескольких операций равного приоритета устанавливается компилятором из условия оптимизации кода программы и не обязательно слева направо. При исчислении логических выражений операции равного приоритета всегда вычисляются слева направо, причем будут вычисляться все или только достаточные операции в зависимости от установленной в среде Турбо Паскаля опции OPTIONS/COMPILER/ COMPLETE BOOLEAN EVAL: при установленном значении этой опции вычисляются все операции отношения, при не установленном - только те, которые достаточны для получения результата.

Это обстоятельство необходимо учитывать при использовании операций отношения с функциями, в которых изменяются глобальные переменные или параметры, передаваемые по имени, например:

Function AddI(var x: Integer): Integer; 

begin {AddI}

inc(x);

AddI := x end {AddI}

var

a,b : Integer; 

begin {main}

if (a > b) or (Addl (a) > 100) then b := a;

.......

При выполнении этого фрагмента значение переменной А будет зависеть от настройки опции: если опция активизирована, значение А всегда наращивается на 1, если не активизирована - только в случае А <= В .

Правила использования операций с операндами различного типа приводятся в табл. 3.1.

Таблица 3.1

Операция

Действие

Тип операндов

Тип результата

not

Отрицание

Логический

Логический

not

То же

Любой целый

Тип операнда

@

Адрес

Любой

Указатель

*

Умножение

Любой целый

Наименьший целый

*

То же

Любой вещественный

Exended

*

Пересечение множеств

Множественный

Множественный

/

Деление

Любой вещественный

Extended

div

Целочисленное деление

Любой целый

Наименьший целый

mod

Остаток от деления

То же

То же

and

Логическое И

Логический

Логический

and

То же

Любой целый

Наименьший целый

shl

Левый сдвиг

То же

То же

shr

Правый сдвиг

То же

То же

+

Сложение

То же

То же

+

То же

Любой вещественный

Extended

+

Объединение множеств

Множественный

Множественный

+

Сцепление строк

Строковый

Строковый

-

Вычитание

Любой целый

Наименьший целый

-

То же

Любой вещественный

Extenden

or

Логическое ИЛИ

Логический

Логический

or

Тоже

Любой целый

Наименьший целый

=

Равно

Любой простой или строковый

Логический

<>

Не равно

То же

То же

<

Меньше

Логический

Логический

<=

Меньше или равно

То же

То же

>

Больше

То же

То же

>=

Больше или равно

То же

То же

При действиях с вещественным типом одним из операндов может быть значение любого целого типа. Результат операций имеет указанный в таблице тип EXTENDED только для установленного в среде Турбо Паскаля режима генерации кода, рассчитанного на арифметический сопроцессор или на его эмуляцию (см. прил.1). Если этот режим не установлен, результат будет иметь значение типа REAL.

Унарная операция @ применяется к операнду любого типа и возвращает результат типа POINTER (см. гл.6), в котором содержится адрес операнда. Пусть, например, задано описание

type

TwoChar = array [1..2] of char; var

Int : integer; TwoCharPtr : ATwoChar;

Тогда оператор

TwoCharPtr := @Int;

приведет к тому, что в TwoCharPtr будет храниться адрес целочисленной переменной INT, которая может теперь интерпретироваться как совокупность двух символов. Поэтому возможен, например, такой оператор:

if TwoCharPtr^[1] = 'С' then...

Если операция @ применяется к процедуре, функции или методу в объекте, ее результатом будет адрес точки входа в эту процедуру (функцию, метод). Этот адрес можно использовать только в подпрограмме, написанной на ассемблере, или в фрагментах INLINE.

В Турбо Паскале определены следующие логические операции:

not - логическое НЕ;

and - логическое И;

or - логическое ИЛИ;

хоr - исключительное ИЛИ. 

Логические операции применимы к операндам целого и логического типов. Если операнды - целые числа, то результат логической операции есть тоже целое число, биты которого (двоичные разряды) формируются из битов операндов по правилам, указанным в табл. 3.2.

Таблица 3.2

Логические операции над данными типа INTEGER (поразрядно)

Операнд 1

Операнд 2

not

and

or

xor

1

-

0

-

-

-

0

-

1

-

-

-

0

0

-

0

0

0

0

1

-

0

1

1

1

0

-

0

1

1

1

1

-

1

1

0

К логическим же в Турбо Паскале обычно относятся и две сдвиговые операции над целыми числами:

i shl j - сдвиг содержимого i на j разрядов влево; освободившиеся младшие

            разряды заполняются нулями;

i shr j - сдвиг содержимого i на j разрядов вправо; освободившиеся старшие

            разряды заполняются нулями.

В этих операциях i и j - выражения любого целого типа.

С помощью программы примера 3.1 можно вывести на экран результат применения логических операций к двум целым числам.

Пример 3.1

{Программа вводит два целых числа и печатает результат применения к ним логических операций. Для выхода из программы ввести Ctrl-z и нажать Enter} 

var

n,m : integer; begin

while not EOF do begin

Write('n,m='); ReadLn(n,m);

WriteLn( '

not=

1 , not n, 'not m);

WriteLnC

and=

' , n and m)

WriteLnC

or =

1 , n or m) ;

WriteLnC

xor=

1 , n xor m)

WriteLn( '

shl=

1 ,n shl m)

WriteLn( '

shr=

1 , n shr m)

end

   

end.

В программе организуется ввод двух произвольных целых чисел и печать результата применения к ним всех логических операций. Для выхода из программы следует нажать Ctrl-z, и Enter.

Логические операции над логическими данными дают результат логического типа по правилам, указанным в табл. 3.3.

Таблица 3.3

Логические операции над данными типа Boolean

Операнд 1

Операнд 2

not

and

or

xor

True

-

False

-

-

-

False

-

True

-

-

-

False

False

-

False

False

False

False

True

-

False

True

True

True

False

-

False

True

True

True

True

-

True

True

False

Операция отношения IN применяется к двум операндам. Первым (левым) операндом должно быть выражение любого порядкового типа, вторым - множество, состоящее из элементов того же типа, или идентификатор множественного типа. Операция дает TRUE, если левый операнд принадлежит множеству, например:

var

с: char; type

digit = set of ' 0 '..' 9 ' ; begin

if с in digit then .......

3.6. СТРУКТУРА ПРОГРАММЫ

Структура любой программной единицы (программы, процедуры или функции) должна быть такой: ;

<Объявление программной единицы>

{Раздел описаний} 

BEGIN

{Раздел исполняемых операторов} 

END <символ конца программной единицы>

Здесь «Объявление программной единицы> - заголовок программы, процедуры или функции; заголовок программы можно опускать без каких-либо последствий для программы; для процедур и функций наличие заголовка обязательно; <символ конца программной единицы> - символ «.» для программы или символ «;» - для процедуры и функции.

Любой из двух разделов программной единицы - раздел описаний или исполняемых операторов, или оба одновременно могут быть пустыми, т.е. не содержать никаких описаний или исполняемых операторов.

В разделе описаний должны содержаться описания всех идентификаторов, используемых в разделе исполняемых операторов. Исключением являются идентификаторы, определенные в интерфейсных частях программных модулей (библиотек), а также

глобальные для процедуры или функции идентификаторы (см. гл. 8). Если программная единица использует идентификатор из интерфейсной части, какого-либо модуля (см. гл. 9), в начале программы в предложении USES необходимо указать имя этого модуля. Последнее не относится к идентификаторам, определенным в стандартном модуле SYSTEM, т.е. имя этого модуля в предложении USES указывать не нужно. Более того, модуль SYSTEM считается предварительно объявленным, поэтому объявление

Uses System;

компилятор расценит как попытку двойного объявления модуля SYSTEM и даст соответствующее сообщение об ошибке. В разделе описаний объявляются идентификаторы типов, объектов, констант, переменных, а также метки, процедуры и функции. Описанию типов и объектов должно предшествовать зарезервированное слово TYPE, описанию констант - CONST, переменных - VAR и меток - LABEL, например: 

type

DigType = set of '0' .. '9' ; 

StrType = string [40]; 

const

N = 100; 

EPS = 1e-9;

var

x,y:real ; 

st :StrType;

label

1b1, 1b2;

В отличие от стандартного Паскаля разделы TYPE, CONST, VAR, LABEL могут следовать друг за другом в любом порядке и встречаться в разделе описаний сколько угодно раз.

Описание процедуры или функции заключается в указании заголовка этой процедуры (функции) и ее тела (подробнее см. в гл. 8).

Структура программных библиотек (модулей) описана в гл.9.